----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    11:09:29 10/07/2013 
-- Design Name: 
-- Module Name:    mult_main_adder_with_control - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

-- Computes B-1 or A\+B\+1
entity mult_main_adder_with_control is
	PORT (
	A : in STD_LOGIC_VECTOR(31 downto 0); -- original digits
	B : in STD_LOGIC_VECTOR(31 downto 0); -- original digits
	
	mult_in : in STD_LOGIC_VECTOR(31 downto 0);
	latch_in : in STD_LOGIC_VECTOR(31 downto 0);
	
	-- 00 => get from normal places
	-- 01 => get from B-1
	-- 10 => get from A-1
	-- 11 => get from B\ + A\ + 1
	CONTROL : in STD_LOGIC_VECTOR(1 downto 0);
	
	ADDER_RESULT_OUT : out STD_LOGIC_VECTOR(31 downto 0);
	ADDER_CARRY_OUT : out STD_LOGIC
	);
end mult_main_adder_with_control;

architecture Behavioral of mult_main_adder_with_control is
	component Adder_32x32 is
	Port (carry_in			: in	STD_LOGIC;							  	--- '1' if we want a carry into the adder
			Arg1				: in	STD_LOGIC_VECTOR (31 downto 0); 	--- Input for additon
			Arg2				: in	STD_LOGIC_VECTOR (31 downto 0); 	--- Input for addition
			Result			: out	STD_LOGIC_VECTOR (31 downto 0); 	--- Main 32 bits of results
			carry_out		: out	STD_LOGIC								--- 
			);
	end component;

	signal adder_carry_in : STD_LOGIC;
	signal adder_arg1 : STD_LOGIC_VECTOR(31 downto 0);
	signal adder_arg2 : STD_LOGIC_VECTOR(31 downto 0);

	signal adder_carry_out_direct : STD_LOGIC;

begin
	adder_inside : Adder_32x32
	port map (
	carry_in => adder_carry_in,
	arg1 => adder_arg1,
	arg2 => adder_arg2,
	result => adder_result_out,
	carry_out => adder_carry_out_direct);
	 
	process(A, B, mult_in, latch_in, control)
	begin
		if (control = "01") then
			-- B negative, so take A-1
			adder_arg1 <= A;
			adder_arg2 <= X"FFFFFFFF";
			adder_carry_in <= '0';
		elsif (control = "10") then
			-- A negative, so take B-1
			adder_arg1 <= B;
			adder_arg2 <= X"FFFFFFFF";
			adder_carry_in <= '0';
		elsif (control = "11") then
			-- A\ + B\ + 1
			adder_arg1 <= not A;
			adder_arg2 <= not B;
			adder_carry_in <= '1';
		else
			-- get from latch and multiplier
			adder_arg1 <= latch_in;
			adder_arg2 <= mult_in;
			adder_carry_in <= '0';
		end if;
	
	end process;
	
	adder_carry_out <= adder_carry_out_direct when control(0) = control(1) else
							 '0';

end Behavioral;

